package cn.zf233.xcloud.web;

import cn.zf233.xcloud.commom.Const;
import cn.zf233.xcloud.commom.R;
import cn.zf233.xcloud.commom.enums.PageNameENUM;
import cn.zf233.xcloud.commom.enums.UserFieldENUM;
import cn.zf233.xcloud.entity.User;
import cn.zf233.xcloud.exception.LoginException;
import cn.zf233.xcloud.service.UserService;
import cn.zf233.xcloud.util.CommonUtil;
import cn.zf233.xcloud.util.KaptchaUtil;
import cn.zf233.xcloud.util.RedisUtil;
import cn.zf233.xcloud.vo.UserVo;
import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Created by zf233 on 2020/12/25
 * 用户请求控制器
 */
@Controller
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private KaptchaUtil kaptchaUtil;

    @Resource
    private RedisUtil redisUtil;

    // 登陆
    @PostMapping(value = "/login")
    @ResponseBody
    public R login(HttpSession session,
                   HttpServletRequest request,
                   HttpServletResponse response,
                   User user,
                   @RequestParam(required = false)
                           Integer remember,
                   String ticket,
                   String randstr) throws LoginException {
        if (kaptchaUtil.test(ticket, randstr, request) != 1) {
            return R.createByErrorMessage("验证码有误，请刷新页面后重新登录");
        }

        // 密码登陆的账号可以是手机或邮箱，所以接收到参数后给邮箱赋值一份
        user.setEmail(user.getPhone());
        R<UserVo> rLogin = userService.login(user);
        if (rLogin.isSuccess()) {
            if (remember != null && remember == 1) {
                Cookie cookie = rememberMe(rLogin.getData().getId(), CommonUtil.getRealIp(request));
                response.addCookie(cookie);
            }
            session.setAttribute(Const.CURRENT_USER, rLogin.getData());
        }
        return rLogin;
    }

    // 邮箱验证码登陆
    @PostMapping(value = "/login/email")
    @ResponseBody
    public R emailCodeLogin(HttpSession session, HttpServletRequest request,
                            HttpServletResponse response,
                            User user,
                            String code,
                            @RequestParam(required = false)
                                    Integer remember,
                            String ticket,
                            String randstr) throws LoginException {
        if (kaptchaUtil.test(ticket, randstr, request) != 1) {
            return R.createByErrorMessage("验证码有误，请刷新页面后重新登录");
        }
        R<UserVo> rLogin = userService.codeLoginEmail(user, code);
        if (rLogin.isSuccess()) {
            if (remember != null && remember == 1) {
                Cookie cookie = rememberMe(rLogin.getData().getId(), CommonUtil.getRealIp(request));
                response.addCookie(cookie);
            }
            session.setAttribute(Const.CURRENT_USER, rLogin.getData());
        }
        return rLogin;
    }

    // 手机验证码登陆
    @PostMapping(value = "/login/phone")
    @ResponseBody
    public R smsCodeLogin(HttpSession session,
                          HttpServletRequest request,
                          HttpServletResponse response,
                          User user,
                          String code,
                          @RequestParam(required = false, defaultValue = "0")
                                  Integer remember,
                          String ticket,
                          String randstr) throws LoginException {
        if (kaptchaUtil.test(ticket, randstr, request) != 1) {
            return R.createByErrorMessage("验证码有误，请刷新页面后重新登录");
        }
        R<UserVo> rLogin = userService.codeLoginSms(user, code);
        if (rLogin.isSuccess()) {
            if (remember != null && remember == 1) {
                Cookie cookie = rememberMe(rLogin.getData().getId(), CommonUtil.getRealIp(request));
                response.addCookie(cookie);
            }
            session.setAttribute(Const.CURRENT_USER, rLogin.getData());
        }
        return rLogin;
    }

    private Cookie rememberMe(Long userId, String realIp) {
        Cookie cookie = new Cookie(Const.USER_REMEMBER_ME_COOKIE_KEY, CommonUtil.base64Encoder(String.valueOf(userId)));
        cookie.setMaxAge((int) Const.USER_REMEMBER_ME_TIMEOUT);
        cookie.setPath("/");
        redisUtil.set(Const.USER_SESSION_STATUS_PREFIX + userId, realIp, Const.USER_REMEMBER_ME_TIMEOUT);
        return cookie;
    }

    // 发送邮箱登陆验证码
    @PostMapping(value = "/login/code/email")
    @ResponseBody
    public R sendEmailLoginCode(User user) throws LoginException {
        return userService.getLoginCodeEmail(user);
    }

    // 发送手机登陆验证码
    @PostMapping(value = "/login/code/phone")
    @ResponseBody
    public R sendSMSLoginCode(User user) throws LoginException {
        return userService.getLoginCodeSms(user);
    }

    // 登出
    @RequestMapping("/quit")
    public String quit(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        UserVo current = (UserVo) session.getAttribute(Const.CURRENT_USER);
        if (current != null && redisUtil.exists(Const.USER_SESSION_STATUS_PREFIX + current.getId())) {
            redisUtil.remove(Const.USER_SESSION_STATUS_PREFIX + current.getId());
        }
        session.invalidate();
        Cookie[] cookies = request.getCookies();
        if (!ObjectUtils.isEmpty(cookies)) {
            for (Cookie cookie : cookies) {
                if (Const.USER_REMEMBER_ME_COOKIE_KEY.equals(cookie.getName())) {
                    cookie.setMaxAge(0);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
            }
        }
        return "redirect:/user/jump/index";
    }

    @RequestMapping("/current/user/get")
    @ResponseBody
    public R getCurrentUserVo(HttpSession session) {
        UserVo currentUser = (UserVo) session.getAttribute(Const.CURRENT_USER);
        if (currentUser == null) {
            return R.createByErrorIllegalArgument("登陆失效，等重新登录");
        }
        return userService.getUserVoByPrimaryKey(currentUser.getId());
    }

    @PostMapping("/applyForLogout")
    @ResponseBody
    public R applyForLogout(HttpSession session) {
        UserVo current = (UserVo) session.getAttribute(Const.CURRENT_USER);
        if (current == null) {
            return R.createByErrorNeedLogin("登陆失效，请重新登录");
        }
        return userService.applyForLogout(CommonUtil.assembleUser(current));
    }

    // 更新用户信息
    @PostMapping(value = "/update")
    @ResponseBody
    public R update(HttpSession session, User user, Integer updateFlag,
                    @RequestParam(required = false) String oldPassword) {
        UserVo currentUser = (UserVo) session.getAttribute(Const.CURRENT_USER);
        if (currentUser == null) {
            return R.createByErrorNeedLogin("登陆失效，请重新登录");
        }
        user.setId(currentUser.getId());
        UserFieldENUM fieldENUM = UserFieldENUM.getUserUpdateFieldENUM(updateFlag);
        if (fieldENUM == null) {
            return R.createByErrorIllegalArgument("更新字段参数有误");
        }
        R response;
        switch (fieldENUM) {
            case NICKNAME:
                response = userService.updateNickname(user);
                break;
            case PASSWORD:
                response = userService.updatePassword(user, oldPassword);
                break;
            case EMAIL:
                response = userService.rebindEmail(user);
                break;
            case PHONE:
                response = userService.rebindPhone(user);
                break;
            default:
                response = R.createByErrorIllegalArgument("信息修改失败，参数有误");
                break;
        }
        if (response.isSuccess()) {
            session.setAttribute(Const.CURRENT_USER, response.getData());
        }
        return response;
    }

    @PostMapping(value = "/rebind/email")
    @ResponseBody
    public R rebindEmail(HttpSession session, User user, String code) {
        UserVo currentUser = (UserVo) session.getAttribute(Const.CURRENT_USER);
        if (currentUser == null) {
            return R.createByErrorNeedLogin("登陆失效，请重新登录");
        }
        user.setId(currentUser.getId());
        R<UserVo> rBind = userService.rebindCheckEmail(user, code);
        if (rBind.isSuccess()) {
            session.setAttribute(Const.CURRENT_USER, rBind.getData());
        }
        return rBind;
    }

    @PostMapping(value = "/rebind/phone")
    @ResponseBody
    public R rebindPhone(HttpSession session, User user, String code) {
        UserVo currentUser = (UserVo) session.getAttribute(Const.CURRENT_USER);
        if (currentUser == null) {
            return R.createByErrorNeedLogin("登陆失效，请重新登录");
        }
        user.setId(currentUser.getId());
        R<UserVo> rBind = userService.rebindCheckPhone(user, code);
        if (rBind.isSuccess()) {
            session.setAttribute(Const.CURRENT_USER, rBind.getData());
        }
        return rBind;
    }

    @RequestMapping(value = "/agree")
    @ResponseBody
    public R agree(HttpSession session, Integer agree) {
        UserVo currentUser = (UserVo) session.getAttribute(Const.CURRENT_USER);
        if (currentUser == null) {
            return R.createByErrorNeedLogin("登陆失效，请重新登录");
        }
        R rAgree = userService.agree(CommonUtil.assembleUser(currentUser), agree);
        if (agree != null && agree == 0 && rAgree.isSuccess()) {
            session.removeAttribute(Const.CURRENT_USER);
        }
        return rAgree;
    }

    @RequestMapping(value = "/chart")
    @ResponseBody
    public R chart(HttpSession session) {
        UserVo currentUser = (UserVo) session.getAttribute(Const.CURRENT_USER);
        if (currentUser == null) {
            return R.createByErrorNeedLogin("登陆失效，请重新登录");
        }
        return userService.chart(CommonUtil.assembleUser(currentUser));
    }

    // 用于页面间的跳转
    @RequestMapping("/jump/{jump}")
    public String jump(HttpSession session, @PathVariable("jump") String jump) {
        UserVo currentUser = (UserVo) session.getAttribute(Const.CURRENT_USER);
        if (!PageNameENUM.exists(jump)) { // 页面不存在
            if (currentUser == null) { // 未登录 转到欢迎页
                return "index";
            }
            return "home"; // 已登陆 转到用户主页
        }

        // 页面存在
        if (currentUser == null) { // 未登陆
            if (PageNameENUM.PAGE_ERROR.getDescribe().equals(jump) ||
                    PageNameENUM.PAGE_NOTICE.getDescribe().equals(jump)) {
                return jump; // 可以链接转到到错误、通知页面
            }
            return "index"; // 否则转到欢迎页
        }

        // 页面存在且已登陆
        if (PageNameENUM.PAGE_ERROR.getDescribe().equals(jump) ||
                PageNameENUM.PAGE_NOTICE.getDescribe().equals(jump)) {
            return jump; // 可以链接转到到错误、通知页面
        }
        return "home"; // 否则转到用户主页
    }
}